#ifndef __UDP_SERVER_HPP__
#define __UDP_SERVER_HPP__

#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <cstring>
#include <string>

// 编写测试UDP服务器
class UdpServer
{
private:
    // 一个套接字对象即可
    int _sock;
    // UDP需要绑定的端口
    uint16_t _port;
    // IP默认为0.0.0.0 即服务器绑定当前机器所有网卡ip
public:
    UdpServer(uint16_t port):_port(port)
    {
        // 初始化
        _sock = socket(AF_INET, SOCK_DGRAM, 0);  // IPV4协议族，数据报式传输，0自动识别类型
        if (_sock < 0){
            std::cout << "socket error" << std::endl;
            exit(0);
        }

        // 初始化sock对象
        struct sockaddr_in server;
        memset(&server, 0, sizeof server);
        server.sin_family = AF_INET;
        server.sin_port = htons(_port);
        server.sin_addr.s_addr = INADDR_ANY;

        // server端绑定0.0.0.0和port
        if (bind(_sock, (sockaddr*)&server, sizeof server) < 0)
        {
            std::cout << "bind error\n";
            exit(1);
        }
        // UDP初始化成功
    }

    void start()
    {
        // 简单循环，接收客户端信息，根据内容进行返回
        struct sockaddr_in client;
        bzero(&client, sizeof client);
        socklen_t client_size = sizeof client;
        char buffer[1024];
        while (true)
        {
            ssize_t n = recvfrom(_sock, buffer, 1024, 0, (sockaddr*)&client, &client_size);
            if (n < 0)
            {
                std::cout << "recvfrom读取error" << std::endl;
            }
            else if (n > 0)
            {
                buffer[n] = '\0';
                // 将client信息提取出来
                uint16_t client_port = ntohs(client.sin_port);  // 别忘了转换字节序
                std::string client_ip = inet_ntoa(client.sin_addr);
                std::cout << "[" << client_ip << ": " << client_port << "]# " << buffer << "[" << n << "]\n";

                // 猫猫回应
                std::string test = buffer;
                const char* messg = nullptr;
                if (test == "摸摸头")
                {
                    messg = "喵~";
                }
                else if (test == "摸摸肚皮") messg = "呜~";
                else messg = "猫猫不懂哦~";

                ssize_t flag = sendto(_sock, messg, strlen(messg), 0, (sockaddr*)&client, sizeof client);
                if (flag < 0) std::cout << "发送失败!sendto error" << std::endl;
            }
        }
    }


    ~UdpServer()
    {
        if (_sock > 0) close(_sock);
    }
};

#endif